Persisting state and data into a database is an important part of many solutions and applications. In the databases, the data can be saved in many formats, such as text, application-specific binary, or a format that is supported by generally available database engines such as MICROSOFT SQL Server. Often times, as an application is developed, the application ends up containing details about the specific storage format or method. In addition, the format of the data when stored is usually different than the format of the data in memory, for example, as it is used by the application. For example, an application may be required to convert a number to a string in order to save to a text file, or construct an XML text block in order to save it into an XML file. Moreover, in order to store the data in a database, the data may need to be converted to a type that is supported by the database engine used.
When converting data formats, the application typically needs to validate the data for the new form the data is taking. For example, an application that needs to convert a “number” to a “string” in order to save an integer into a text file may be required to perform a length check on the number if the file has limited space allocated for the data being written. The application also needs to check the integrity of the data before actually storing the data in its new form. In these applications, the validation and integrity-checking code is typically tightly integrated with the application code—i.e., the data conversion and rules for validating the converted data types and checking the integrity of the converted data before storing the data ends up becoming an integral part of the application.
The integration of the validation and integrity-checking code with the application code presents many problems. A major problem is the time and energy required to add or change a storage type in an application where the validation and integrity-checking code is tightly integrated with the application code. For example, in order to add or introduce a new storage target in an application that is using an existing storage type, all of the validation and integrity-checking needs to be repeated in the application for the new storage target. Also, where an application is using multiple types of storage, changes to any of the storage types requires all of the validation and integrity-checking to be repeated in the application for each of the storage types that is being changed.
The tight integration of code is also present in the development of user interfaces (UIs). Many server, and sometimes client, software products provide an administrative UI that allows users, such as administrators or end users, to locally or remotely configure the settings for the various aspects of the products, and allows users to monitor the health statistics of the running software process. In the server management UI, there are typically a set of nodes representing different deployment or management entities.
By way of example, a server's administrative console may include a set of deployment/management entities such as, an Active Directory forest, domains inside the forest, server pools, servers associated with the pools, users that are assigned to different pools, etc. Each type of node may represent a logical deployment/management entity that is associated with, for example, different sets of properties, management tasks and extensibility points. In conventional implementations, the management software typically “hard codes” a set of UI elements for each entity, and each entity has the built-in knowledge of what set of UI elements it needs to display as well as how to organize and render these elements. In these implementations of the management software, the coupling is very tight between the deployment/management entities and their corresponding UI elements. A major drawback to the tight coupling between the deployment/management entities and their corresponding UI elements is that a change to the logic in the UI elements or to the deployment/management entities usually causes a rebuild of several binaries in the product.
Another drawback is the inflexibility caused by the tight coupling between the deployment/management entities and their corresponding UI elements. For example, if a set of new UI elements needs to be added for a particular deployment/management entity, the entity code needs to be changed, rebuilt, tested and redistributed to, for example, a customer with the knowledge of these newly added UI elements. The customer needs to know how to create, organize, render and communicate with these UI elements. Moreover, the code for these new UI elements needs to be written, built, tested and redistributed to the customer as well. The cost associated with these steps can be very high, and may force the development of incremental, yet important additions/changes, which could otherwise reach the targeted customers more quickly and drive up customer satisfaction, to be “pushed off” or delayed, for example, to a next release of the product.
It would be desirable to have a technique that allows for the decoupling of various functionalities from the application code.